package pe.com.casadesign.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.stereotype.Repository;

import pe.com.casadesign.dao.ItemDAO;
import pe.com.casadesign.domain.Componente;
import pe.com.casadesign.domain.Item;
import pe.com.casadesign.domain.ItemComponente;
import pe.com.casadesign.domain.LineaOrdenCompra;
import pe.com.casadesign.domain.ListaItem;
import pe.com.casadesign.domain.ListaItemComponente;
import pe.com.casadesign.domain.Moneda;
import pe.com.casadesign.domain.Producto;
import pe.com.casadesign.domain.Proveedor;
import pe.com.casadesign.domain.Tienda;

/**
 * Implementacion de ItemDAO.
 * 
 * @author Pedro Vera
 * 
 */
@Repository
public class ItemDAOImpl implements ItemDAO {
	private static final Logger logger = LoggerFactory.getLogger(ItemDAOImpl.class);
	
	// Nombre Procedimientos Almacenados
	private static String SP_LISTAR_ITEM = "SP_LISTAR_ITEM";
	private static String SP_OBTENER_ITEM = "SP_OBTENER_ITEM";
	private static String SP_REGISTRAR_ITEM = "SP_REGISTRAR_ITEM";
	private static String SP_CONSULTAR_ITEM = "SP_CONSULTAR_ITEM";
	private static String SP_LISTAR_ITEM_PRODUCTO = "SP_LISTAR_ITEM_PRODUCTO"; 
	private static String SP_LISTAR_ITEM_COMP_PRODUCTO = "SP_LISTAR_ITEM_COMP_PRODUCTO";
	private static String SP_MODIFICAR_ITEM = "SP_MODIFICAR_ITEM";
	private static String SP_REGISTRAR_ITEM_COMPONENTE = "SP_REGISTRAR_ITEM_COMPONENTE";
	private static String SP_LIMPIAR_ITEM_COMPONENTE = "SP_LIMPIAR_ITEM_COMPONENTE";
	private static String SP_ACTUALIZAR_ESTADO_ITEM = "SP_ACTUALIZAR_ESTADO_ITEM";
	private static String SP_MODIFICAR_ITEM_COMPONENTE= "SP_MODIFICAR_ITEM_COMPONENTE";
	private static String SP_CONSULTAR_ITEM_INVENTARIO = "SP_CONSULTAR_ITEM_INVENTARIO";
	private static String SP_LISTAR_ITEM_COMPONENTE = "SP_LISTAR_ITEM_COMPONENTE";
	private static String SP_ACTUALIZAR_ESTADO_TIENDA_ITEM = "SP_ACTUALIZAR_ESTADO_TIENDA_ITEM";
	
	// Parametros de Entrada
	private static String PARAM_CODITEM = "p_coditem";
	private static String PARAM_CODITEM_SALIDA = "p_coditem_salida";
	private static String PARAM_CODPRODUCTO = "p_codproducto";
	private static String PARAM_CODIFICACION = "p_codificacion"; 
	private static String PARAM_CODPROVEEDOR = "p_codproveedor"; 
	private static String PARAM_ORIGEN = "p_origen"; 
	private static String PARAM_PROPIEDADES = "p_propiedades";
	private static String PARAM_INCIDENCIAS = "p_incidencias";
	private static String PARAM_PRECIOCOMPRA = "p_preciocompra"; 
	private static String PARAM_CODMONEDA = "p_codmoneda"; 
	private static String PARAM_CODOC = "p_codoc"; 
	private static String PARAM_NROLINEA = "p_nrolinea";
	private static String PARAM_CODTIENDA = "p_codtienda";
	private static String PARAM_ESTADO = "p_estado";
	private static String PARAM_CODINVENTARIO = "p_codinventario";
	
	private static String PARAM_ITEM_CODIFICACION = "p_codificacion";
	private static String PARAM_ITEM_CODCOMPONENTE = "p_codcomponente";
	private static String PARAM_PRODUCTO_CODPRODUCTO = "p_codproducto";
	private static String PARAM_ITEM_CODITEMUNION = "p_coditemunion";
	private static String PARAM_ITEM_UNIONITEM = "p_unionitem";
	private static String PARAM_ITEM_CODITEM = "p_coditem";
	
	private static String PARAM_CRITERIO = "p_criterio";
	private static String PARAM_VALOR = "p_valor";
	
	// Parametros de Salida
	private static String CODITEM = "CODITEM";
	private static String CODPRODUCTO = "CODPRODUCTO";
	private static String CODPRODUCTOPROVEEDOR = "CODPRODUCTOPROVEEDOR";
	private static String CODIFICACION = "CODIFICACION"; 
	private static String CODPROVEEDOR = "CODPROVEEDOR"; 
	private static String ORIGEN = "ORIGEN"; 
	private static String PROPIEDADES = "PROPIEDADES";
	private static String INCIDENCIAS = "INCIDENCIAS";
	private static String PRECIOCOMPRA = "PRECIOCOMPRA"; 
	private static String CODMONEDA = "CODMONEDA"; 
	private static String CODOC = "CODOC"; 
	private static String NROLINEA = "NROLINEA";
	private static String CODTIENDA = "CODTIENDA";
	private static String ESTADO = "ESTADO"; 
	private static String FECHAREGISTRO = "FECHAREGISTRO";
	
	private static String COMPONENTE_CODITEM = "CODITEM";
	private static String COMPONENTE_CODCOMPONENTE = "CODCOMPONENTE";
	private static String COMPONENTE_DESCRIPCION = "DESCRIPCION";
	private static String COMPONENTE_CODIFICACION = "CODIFICACION";
	private static String COMPONENTE_CODITEMUNION = "CODITEMUNION";
	private static String COMPONENTE_UNIONITEM = "UNIONITEM";
	
	
	private static String PRODUCTO_DESCRIPCION = "DESCRIPCION";
	private static String PRODUCTO_PRECIOVENTAMINIMO = "PRECIOVENTAMINIMO";
	private static String PRODUCTO_PRECIOVENTAMAXIMO = "PRECIOVENTAMAXIMO";
	private static String PRODUCTO_ALTO = "ALTO";
	private static String PRODUCTO_ANCHO = "ANCHO";
	private static String PRODUCTO_LARGO = "LARGO";

	private static String LISTADO = "LISTADO";
	private static String LISTADO_LINEAS = "LISTADO_LINEAS";
	
	private static String TOTAL_FILAS_AFECTADAS = "#update-count-1";
	
	private JdbcTemplate jdbcTemplate;

	@Autowired
    public void setDataSource(DataSource dataSource)
    {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }
	
	@Override
	public ListaItem listarItem(String criterio, 
			 					String valor){
		logger.info("listarItem");

		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_LISTAR_ITEM).
	    						  returningResultSet(LISTADO, new RowMapper<Item>(){
									@Override
									public Item mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
								        final Item item = new Item();
								        item.setCodItem(rs.getInt(CODITEM));
								        
								        Producto producto = new Producto();
								        producto.setCodigo(rs.getInt(CODPRODUCTO));
								        producto.setCodProductoProveedor(rs.getString(CODPRODUCTOPROVEEDOR));
								        producto.setDescripcion(rs.getString(PRODUCTO_DESCRIPCION));
								        item.setProducto(producto);
								        
								        item.setCodificacion(rs.getString(CODIFICACION));
								        
								        Proveedor proveedor = new Proveedor();
								        proveedor.setCodProveedor(rs.getInt(CODPROVEEDOR));
								        item.setProveedor(proveedor);
								        
								        item.setOrigen(rs.getString(ORIGEN));
								        item.setPropiedades(rs.getString(PROPIEDADES));
								        item.setIncidencias(rs.getString(INCIDENCIAS));
								        item.setPrecioCompra(rs.getDouble(PRECIOCOMPRA));
								        
								        Moneda moneda = new Moneda();
								        moneda.setCodigo(rs.getInt(CODMONEDA));
								        item.setMoneda(moneda);
								        
								        LineaOrdenCompra lineaOrdenCompra = new LineaOrdenCompra(); 
								        lineaOrdenCompra.setCodOC(rs.getInt(CODOC));
								        lineaOrdenCompra.setNumeroLinea(rs.getInt(NROLINEA));
								        item.setLineaOrdenCompra(lineaOrdenCompra);
								        
								        Tienda tienda = new Tienda();
								        tienda.setCodigo(rs.getInt(CODTIENDA));
								        item.setTienda(tienda);
								        
								        item.setEstado(rs.getString(ESTADO));
								        item.setFechaRegistro(rs.getDate(FECHAREGISTRO).toString());
								        return item;
								    }
	    						  }
								);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CRITERIO, criterio)
	    								.addValue(PARAM_VALOR, valor); 

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);

        // Obteniendo lista generada de ejecutar SP
		@SuppressWarnings("unchecked")
		List<Item> listaItem= (List<Item>)data.get(LISTADO);
        
		// Instanciando objeto ListaItem
		ListaItem listaItemResultado = new ListaItem();
        // Estableciendo resultado al objeto listaItemResultado
		
		listaItemResultado.setLista(listaItem);
        
        if (logger.isDebugEnabled() && listaItemResultado != null)
        {
            logger.debug("size=" + listaItemResultado.size());
        }
        return listaItemResultado;
	}
	
	@Override
	public ListaItem listarItemProducto(Producto producto){
		logger.info("listarItemProducto");

		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_LISTAR_ITEM_PRODUCTO).
	    						  returningResultSet(LISTADO, new RowMapper<Item>(){
									@Override
									public Item mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
								        final Item item = new Item();
								        item.setCodItem(rs.getInt(CODITEM));
								        
								        Producto producto = new Producto();
								        producto.setCodigo(rs.getInt(CODPRODUCTO));
								        producto.setCodProductoProveedor(rs.getString(CODPRODUCTOPROVEEDOR));
								        producto.setDescripcion(rs.getString(PRODUCTO_DESCRIPCION));
								        item.setProducto(producto);
								        
								        item.setCodificacion(rs.getString(CODIFICACION));
								        
								        Proveedor proveedor = new Proveedor();
								        proveedor.setCodProveedor(rs.getInt(CODPROVEEDOR));
								        item.setProveedor(proveedor);
								        
								        item.setOrigen(rs.getString(ORIGEN));
								        item.setPropiedades(rs.getString(PROPIEDADES));
								        item.setIncidencias(rs.getString(INCIDENCIAS));
								        item.setPrecioCompra(rs.getDouble(PRECIOCOMPRA));
								        
								        Moneda moneda = new Moneda();
								        moneda.setCodigo(rs.getInt(CODMONEDA));
								        item.setMoneda(moneda);
								        
								        LineaOrdenCompra lineaOrdenCompra = new LineaOrdenCompra(); 
								        lineaOrdenCompra.setCodOC(rs.getInt(CODOC));
								        lineaOrdenCompra.setNumeroLinea(rs.getInt(NROLINEA));
								        item.setLineaOrdenCompra(lineaOrdenCompra);
								        
								        Tienda tienda = new Tienda();
								        tienda.setCodigo(rs.getInt(CODTIENDA));
								        item.setTienda(tienda);
								        
								        item.setEstado(rs.getString(ESTADO));
								        item.setFechaRegistro(rs.getDate(FECHAREGISTRO).toString());
								        return item;
								    }
	    						  }
								);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_PRODUCTO_CODPRODUCTO, producto.getCodigo()); 

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);

        // Obteniendo lista generada de ejecutar SP
		@SuppressWarnings("unchecked")
		List<Item> listaItem= (List<Item>)data.get(LISTADO);
        
		// Instanciando objeto ListaItem
		ListaItem listaItemResultado = new ListaItem();
        // Estableciendo resultado al objeto listaTiendaResultado
		listaItemResultado.setLista(listaItem);
        
        if (logger.isDebugEnabled() && listaItemResultado != null)
        {
            logger.debug("size=" + listaItemResultado.size());
        }
        return listaItemResultado;
	}
	
	@Override
	public ListaItem listarItemCompProducto(Producto producto){
		logger.info("listarItemCompProducto");

		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_LISTAR_ITEM_COMP_PRODUCTO).
	    						  returningResultSet(LISTADO, new RowMapper<Item>(){
									@Override
									public Item mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
								        final Item item = new Item();
								        item.setCodItem(rs.getInt(CODITEM));
								        
								        Producto producto = new Producto();
								        producto.setCodigo(rs.getInt(CODPRODUCTO));
								        producto.setCodProductoProveedor(rs.getString(CODPRODUCTOPROVEEDOR));
								        producto.setDescripcion(rs.getString(PRODUCTO_DESCRIPCION));
								        item.setProducto(producto);
								        
								        item.setCodificacion(rs.getString(CODIFICACION));
								        
								        Proveedor proveedor = new Proveedor();
								        proveedor.setCodProveedor(rs.getInt(CODPROVEEDOR));
								        item.setProveedor(proveedor);
								        
								        item.setOrigen(rs.getString(ORIGEN));
								        item.setPropiedades(rs.getString(PROPIEDADES));
								        item.setIncidencias(rs.getString(INCIDENCIAS));
								        item.setPrecioCompra(rs.getDouble(PRECIOCOMPRA));
								        
								        Moneda moneda = new Moneda();
								        moneda.setCodigo(rs.getInt(CODMONEDA));
								        item.setMoneda(moneda);
								        
								        LineaOrdenCompra lineaOrdenCompra = new LineaOrdenCompra(); 
								        lineaOrdenCompra.setCodOC(rs.getInt(CODOC));
								        lineaOrdenCompra.setNumeroLinea(rs.getInt(NROLINEA));
								        item.setLineaOrdenCompra(lineaOrdenCompra);
								        
								        Tienda tienda = new Tienda();
								        tienda.setCodigo(rs.getInt(CODTIENDA));
								        item.setTienda(tienda);
								        
								        item.setEstado(rs.getString(ESTADO));
								        item.setFechaRegistro(rs.getDate(FECHAREGISTRO).toString());
								        return item;
								    }
	    						  }
								);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_PRODUCTO_CODPRODUCTO, producto.getCodigo()); 

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);

        // Obteniendo lista generada de ejecutar SP
		@SuppressWarnings("unchecked")
		List<Item> listaItem= (List<Item>)data.get(LISTADO);
        
		// Instanciando objeto ListaItem
		ListaItem listaItemResultado = new ListaItem();
        // Estableciendo resultado al objeto listaTiendaResultado
		listaItemResultado.setLista(listaItem);
        
        if (logger.isDebugEnabled() && listaItemResultado != null)
        {
            logger.debug("size=" + listaItemResultado.size());
        }
        return listaItemResultado;
	}
	
	@Override
	public Item obtenerItem(Item item){
		logger.info("obtenerItem");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_OBTENER_ITEM).
								  returningResultSet(LISTADO, new RowMapper<Item>(){
									@Override
									public Item mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
								        final Item item = new Item();
								        item.setCodItem(rs.getInt(CODITEM));
								        
								        Producto producto = new Producto();
								        producto.setCodigo(rs.getInt(CODPRODUCTO));
								        producto.setCodProductoProveedor(rs.getString(CODPRODUCTOPROVEEDOR));
								        producto.setDescripcion(rs.getString(PRODUCTO_DESCRIPCION));
								        item.setProducto(producto);
								        
								        item.setCodificacion(rs.getString(CODIFICACION));
								        
								        Proveedor proveedor = new Proveedor();
								        proveedor.setCodProveedor(rs.getInt(CODPROVEEDOR));
								        item.setProveedor(proveedor);
								        
								        item.setOrigen(rs.getString(ORIGEN));
								        item.setPropiedades(rs.getString(PROPIEDADES));
								        item.setIncidencias(rs.getString(INCIDENCIAS));
								        item.setPrecioCompra(rs.getDouble(PRECIOCOMPRA));
								        
								        Moneda moneda = new Moneda();
								        moneda.setCodigo(rs.getInt(CODMONEDA));
								        item.setMoneda(moneda);
								        
								        LineaOrdenCompra lineaOrdenCompra = new LineaOrdenCompra(); 
								        lineaOrdenCompra.setCodOC(rs.getInt(CODOC));
								        lineaOrdenCompra.setNumeroLinea(rs.getInt(NROLINEA));
								        item.setLineaOrdenCompra(lineaOrdenCompra);
								        
								        Tienda tienda = new Tienda();
								        tienda.setCodigo(rs.getInt(CODTIENDA));
								        item.setTienda(tienda);
								        
								        item.setEstado(rs.getString(ESTADO));
								        item.setFechaRegistro(rs.getDate(FECHAREGISTRO).toString());
								        return item;
								    }
								  }
								)
								.returningResultSet(LISTADO_LINEAS,	new RowMapper<ItemComponente>(){
									@Override
									public ItemComponente mapRow(final ResultSet rs,final int numRow) throws SQLException {
										final ItemComponente itemComponente = new ItemComponente();
										
										itemComponente.setCodComponente(rs.getInt(COMPONENTE_CODCOMPONENTE));
										itemComponente.setCodItem(rs.getInt(COMPONENTE_CODITEM));
										itemComponente.setCodificacion(rs.getString(COMPONENTE_CODIFICACION));
										itemComponente.setUnionItem(rs.getString(COMPONENTE_UNIONITEM));
										
										Item itemUnion = new Item();
										itemUnion.setCodItem(rs.getInt(COMPONENTE_CODITEMUNION));
										itemComponente.setItem(itemUnion);
										
										Componente componente = new Componente();
										componente.setDescripcion(COMPONENTE_DESCRIPCION);
										itemComponente.setComponente(componente);
									
										return itemComponente;
									}
								});

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODITEM, item.getCodItem());

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);

        // Obteniendo lista generada de ejecutar SP
		@SuppressWarnings("unchecked")
		List<Item> listaItem = (List<Item>)data.get(LISTADO);
        
		// Declarando objeto item Obtenido
		Item itemObtenido = null;
		
		if (listaItem != null && listaItem.size()>0){
			// Obteniendo el primer elemento de la lista de item
			itemObtenido = listaItem.get(0);
			// Obteniendo lista de lineas generada de ejecutar SP
			@SuppressWarnings("unchecked")
			List<ItemComponente> listaItemComponente = (List<ItemComponente>) data.get(LISTADO_LINEAS);

			// Instanciando objeto listaItemComponente
			ListaItemComponente listaItemComponenteResultado = new ListaItemComponente();
			// Estableciendo resultado al objeto ListaItemComponente
			listaItemComponenteResultado.setLista(listaItemComponente);
			// Asignando lista de lineas al objeto Item creado
			itemObtenido.setListaItemComponente(listaItemComponenteResultado);
		}
        
        if (logger.isDebugEnabled() && listaItem != null)
        {
            logger.debug("size=" + listaItem.size());
        }
        
		return itemObtenido;
	}
	
	@Override
	public boolean registrarItem(Item item) {
		logger.info("registrarItem");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_REGISTRAR_ITEM);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	                                    .addValue(PARAM_CODITEM, item.getCodItem())
	    								.addValue(PARAM_CODPRODUCTO, item.getProducto().getCodigo())
	    								.addValue(PARAM_CODIFICACION, item.getCodificacion())
	    								.addValue(PARAM_CODPROVEEDOR , item.getProveedor().getCodProveedor())
	    								.addValue(PARAM_ORIGEN, item.getOrigen())
	    								.addValue(PARAM_PROPIEDADES, item.getPropiedades())
	    								.addValue(PARAM_INCIDENCIAS, item.getIncidencias())
	    								.addValue(PARAM_PRECIOCOMPRA, item.getPrecioCompra())
	    								.addValue(PARAM_CODMONEDA, item.getMoneda().getCodigo())
	    								.addValue(PARAM_CODOC, item.getLineaOrdenCompra().getCodOC())
	    								.addValue(PARAM_NROLINEA, item.getLineaOrdenCompra().getNumeroLinea())
	    								.addValue(PARAM_CODTIENDA, item.getTienda().getCodigo())	
	    								.addValue(PARAM_ESTADO, item.getEstado());
		
		
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    int totalRegistrosAfectado = (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	    
	    // Obteniendo codigo de item
	    int codigoItem = (Integer)data.get(PARAM_CODITEM_SALIDA);

	    // Estableciendo codigo de item
	    item.setCodItem(codigoItem);
	    
	    // ==== Registro de ItemsComponentes ====
	    totalRegistrosAfectado += registrarItemComponente(item);
	    
	    return totalRegistrosAfectado > 0;
	}

	@Override
	public Item consultarItem(Item item){
		logger.info("consultarItem");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_CONSULTAR_ITEM).
								  returningResultSet(LISTADO, new RowMapper<Item>(){
									@Override
									public Item mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
								        final Item item = new Item();
								        item.setCodItem(rs.getInt(CODITEM));
								        
								        Producto producto = new Producto();
								        producto.setCodigo(rs.getInt(CODPRODUCTO));
								        producto.setCodProductoProveedor(rs.getString(CODPRODUCTOPROVEEDOR));
								        producto.setDescripcion(rs.getString(PRODUCTO_DESCRIPCION));
								        producto.setPrecioVentaMinimo(rs.getDouble(PRODUCTO_PRECIOVENTAMINIMO));
								        producto.setPrecioVentaMaximo(rs.getDouble(PRODUCTO_PRECIOVENTAMAXIMO));
								        producto.setAlto(rs.getDouble(PRODUCTO_ALTO));
								        producto.setAncho(rs.getDouble(PRODUCTO_ANCHO));
								        producto.setLargo(rs.getDouble(PRODUCTO_LARGO));
								        item.setProducto(producto);
								        
								        item.setCodificacion(rs.getString(CODIFICACION));
								        
								        Proveedor proveedor = new Proveedor();
								        proveedor.setCodProveedor(rs.getInt(CODPROVEEDOR));
								        item.setProveedor(proveedor);
								        
								        item.setOrigen(rs.getString(ORIGEN));
								        item.setPropiedades(rs.getString(PROPIEDADES));
								        item.setIncidencias(rs.getString(INCIDENCIAS));
								        item.setPrecioCompra(rs.getDouble(PRECIOCOMPRA));
								        
								        Moneda moneda = new Moneda();
								        moneda.setCodigo(rs.getInt(CODMONEDA));
								        item.setMoneda(moneda);
								        
								        LineaOrdenCompra lineaOrdenCompra = new LineaOrdenCompra(); 
								        lineaOrdenCompra.setCodOC(rs.getInt(CODOC));
								        lineaOrdenCompra.setNumeroLinea(rs.getInt(NROLINEA));
								        item.setLineaOrdenCompra(lineaOrdenCompra);
								        
								        Tienda tienda = new Tienda();
								        tienda.setCodigo(rs.getInt(CODTIENDA));
								        item.setTienda(tienda);
								        
								        item.setEstado(rs.getString(ESTADO));
								        item.setFechaRegistro(rs.getDate(FECHAREGISTRO).toString());
								        return item;
								    }
								  }
								)
								.returningResultSet(LISTADO_LINEAS,	new RowMapper<ItemComponente>(){
									@Override
									public ItemComponente mapRow(final ResultSet rs,final int numRow) throws SQLException {
										final ItemComponente itemComponente = new ItemComponente();
										
										itemComponente.setCodComponente(rs.getInt(COMPONENTE_CODCOMPONENTE));
										itemComponente.setCodItem(rs.getInt(COMPONENTE_CODITEM));
										itemComponente.setCodificacion(rs.getString(COMPONENTE_CODIFICACION));
                                        itemComponente.setUnionItem(rs.getString(COMPONENTE_UNIONITEM));
										
										Item itemUnion = new Item();
										itemUnion.setCodItem(rs.getInt(COMPONENTE_CODITEMUNION));
										itemComponente.setItem(itemUnion);
									
										return itemComponente;
									}
								});

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	                               .addValue(PARAM_ITEM_CODIFICACION, item.getCodificacion());

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);

        // Obteniendo lista generada de ejecutar SP
		@SuppressWarnings("unchecked")
		List<Item> listaItem = (List<Item>)data.get(LISTADO);
        
		// Declarando objeto item Obtenido
		Item itemObtenido = null;
		
		if (listaItem != null && listaItem.size()>0){
			// Obteniendo el primer elemento de la lista de item
			itemObtenido = listaItem.get(0);
			// Obteniendo lista de lineas generada de ejecutar SP
			@SuppressWarnings("unchecked")
			List<ItemComponente> listaItemComponente = (List<ItemComponente>) data.get(LISTADO_LINEAS);

			// Instanciando objeto listaItemComponente
			ListaItemComponente listaItemComponenteResultado = new ListaItemComponente();
			// Estableciendo resultado al objeto ListaItemComponente
			listaItemComponenteResultado.setLista(listaItemComponente);
			// Asignando lista de lineas al objeto Item creado
			itemObtenido.setListaItemComponente(listaItemComponenteResultado);
		}
        
        if (logger.isDebugEnabled() && listaItem != null)
        {
            logger.debug("size=" + listaItem.size());
        }
        
		return itemObtenido;
	}
	
	private int registrarItemComponente(Item item){
		logger.info("registrarItemComponente");
		
		int totalRegistrosAfectado = 0;
		
		// Obteniendo lista de lineas de la guia a agregar
	    ListaItemComponente listaItemComponente = item.getListaItemComponente();
	    
	    // Si existen lineas entonces registrarlos
	    if(listaItemComponente != null && listaItemComponente.getLista() != null){
		    // Instanciando variable para llamado de SP
		    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_REGISTRAR_ITEM_COMPONENTE);
	
		    for (ItemComponente itemComponente : listaItemComponente.getLista()){
		    	// Estableciendo codigo de item
		    	itemComponente.setCodItem(item.getCodItem());
		    	
			    // Estableciendo parametros de entrada al SP
			    SqlParameterSource parametrosDetalle = new MapSqlParameterSource()
						    								.addValue(PARAM_CODITEM, itemComponente.getCodItem())
						    								.addValue(PARAM_ITEM_CODCOMPONENTE , itemComponente.getCodComponente())
						    								.addValue(PARAM_ITEM_CODIFICACION, itemComponente.getCodificacion())
						    								.addValue(PARAM_ITEM_CODITEMUNION, itemComponente.getItem()==null?null:itemComponente.getItem().getCodItem())
						    								.addValue(PARAM_ITEM_UNIONITEM, itemComponente.getUnionItem());
			    
			    // Establecer parametros y ejecutar SP
			    Map<String,Object> dataDetalle = llamarSP.execute(parametrosDetalle);
			    
			    // Obteniendo el total de filas afectadas al ejecutar SP
			    totalRegistrosAfectado += (Integer) dataDetalle.get(TOTAL_FILAS_AFECTADAS);
		    }
	    }
	    
	    return totalRegistrosAfectado;
	}
	
	public int modificarItem(Item item){
		logger.info("modificarItem");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_MODIFICAR_ITEM);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODITEM, item.getCodItem())
	    								.addValue(PARAM_ESTADO, item.getEstado())
	    								.addValue(PARAM_CODIFICACION, item.getCodificacion())
	    								.addValue(PARAM_PRECIOCOMPRA, item.getPrecioCompra())
	    								.addValue(PARAM_CODMONEDA, item.getMoneda()==null?null:item.getMoneda().getCodigo())
	    								.addValue(PARAM_CODTIENDA,item.getTienda()==null?null:item.getTienda().getCodigo());
	    
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    int totalRegistrosAfectado = (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	    
	    totalRegistrosAfectado += limpiarItemComponente(item);
	    
	    // ==== Registro de ItemsComponentes ====
	    totalRegistrosAfectado += registrarItemComponente(item);
	    
	    	        
	    return totalRegistrosAfectado;
	}

	@Override
	public Item consultarItemComponente(ItemComponente itemComponente){
		logger.info("consultarItemComponente");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_CONSULTAR_ITEM).
								  returningResultSet(LISTADO, new RowMapper<Item>(){
									@Override
									public Item mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
								        final Item item = new Item();
								        item.setCodItem(rs.getInt(CODITEM));
								        
								        Producto producto = new Producto();
								        producto.setCodigo(rs.getInt(CODPRODUCTO));
								        producto.setCodProductoProveedor(rs.getString(CODPRODUCTOPROVEEDOR));
								        producto.setDescripcion(rs.getString(PRODUCTO_DESCRIPCION));
								        producto.setPrecioVentaMinimo(rs.getDouble(PRODUCTO_PRECIOVENTAMINIMO));
								        producto.setPrecioVentaMaximo(rs.getDouble(PRODUCTO_PRECIOVENTAMAXIMO));
								        producto.setAlto(rs.getDouble(PRODUCTO_ALTO));
								        producto.setAncho(rs.getDouble(PRODUCTO_ANCHO));
								        producto.setLargo(rs.getDouble(PRODUCTO_LARGO));
								        item.setProducto(producto);
								        
								        item.setCodificacion(rs.getString(CODIFICACION));
								        
								        Proveedor proveedor = new Proveedor();
								        proveedor.setCodProveedor(rs.getInt(CODPROVEEDOR));
								        item.setProveedor(proveedor);
								        
								        item.setOrigen(rs.getString(ORIGEN));
								        item.setPropiedades(rs.getString(PROPIEDADES));
								        item.setIncidencias(rs.getString(INCIDENCIAS));
								        item.setPrecioCompra(rs.getDouble(PRECIOCOMPRA));
								        
								        Moneda moneda = new Moneda();
								        moneda.setCodigo(rs.getInt(CODMONEDA));
								        item.setMoneda(moneda);
								        
								        LineaOrdenCompra lineaOrdenCompra = new LineaOrdenCompra(); 
								        lineaOrdenCompra.setCodOC(rs.getInt(CODOC));
								        lineaOrdenCompra.setNumeroLinea(rs.getInt(NROLINEA));
								        item.setLineaOrdenCompra(lineaOrdenCompra);
								        
								        Tienda tienda = new Tienda();
								        tienda.setCodigo(rs.getInt(CODTIENDA));
								        item.setTienda(tienda);
								        
								        item.setEstado(rs.getString(ESTADO));
								        item.setFechaRegistro(rs.getDate(FECHAREGISTRO).toString());
								        return item;
								    }
								  }
								)
								.returningResultSet(LISTADO_LINEAS,	new RowMapper<ItemComponente>(){
									@Override
									public ItemComponente mapRow(final ResultSet rs,final int numRow) throws SQLException {
										final ItemComponente itemComponente = new ItemComponente();
										
										itemComponente.setCodComponente(rs.getInt(COMPONENTE_CODCOMPONENTE));
										itemComponente.setCodItem(rs.getInt(COMPONENTE_CODITEM));
										itemComponente.setCodificacion(rs.getString(COMPONENTE_CODIFICACION));
									
										return itemComponente;
									}
								});

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	                               .addValue(PARAM_ITEM_CODIFICACION, itemComponente.getCodificacion());

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);

        // Obteniendo lista generada de ejecutar SP
		@SuppressWarnings("unchecked")
		List<Item> listaItem = (List<Item>)data.get(LISTADO);
        
		// Declarando objeto item Obtenido
		Item itemObtenido = null;
		
		if (listaItem != null && listaItem.size()>0){
			// Obteniendo el primer elemento de la lista de item
			itemObtenido = listaItem.get(0);
			// Obteniendo lista de lineas generada de ejecutar SP
			@SuppressWarnings("unchecked")
			List<ItemComponente> listaItemComponente = (List<ItemComponente>) data.get(LISTADO_LINEAS);

			// Instanciando objeto listaItemComponente
			ListaItemComponente listaItemComponenteResultado = new ListaItemComponente();
			// Estableciendo resultado al objeto ListaItemComponente
			listaItemComponenteResultado.setLista(listaItemComponente);
			// Asignando lista de lineas al objeto Item creado
			itemObtenido.setListaItemComponente(listaItemComponenteResultado);
		}
        
        if (logger.isDebugEnabled() && listaItem != null)
        {
            logger.debug("size=" + listaItem.size());
        }
        
		return itemObtenido;
	}
	
	
	private int limpiarItemComponente(Item item) {
		logger.info("limpiarItemComponente");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_LIMPIAR_ITEM_COMPONENTE);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODITEM, item.getCodItem());
	    
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    int totalRegistrosAfectado = (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	    
	    return totalRegistrosAfectado;
	}
	
	public int actualizarEstadoItem(Item item){
		logger.info("actualizarEstadoItem");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_ACTUALIZAR_ESTADO_ITEM);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODITEM, item.getCodItem())
	    								.addValue(PARAM_ESTADO, item.getEstado());
	    
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    int totalRegistrosAfectado = (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	        
	    return totalRegistrosAfectado;
	}
	
	public int actualizarEstadoTiendaItem(Item item){
		logger.info("actualizarEstadoTiendaItem");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_ACTUALIZAR_ESTADO_TIENDA_ITEM);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODITEM, item.getCodItem())
	    								.addValue(PARAM_CODTIENDA, item.getTienda().getCodigo())
	    								.addValue(PARAM_ESTADO, item.getEstado());
	    
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    int totalRegistrosAfectado = (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	        
	    return totalRegistrosAfectado;
	}
	
	public int modificarItemComponente(ItemComponente itemComponente){
		logger.info("modificarItemComponente");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_MODIFICAR_ITEM_COMPONENTE);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODITEM, itemComponente.getCodItem())
	    								.addValue(PARAM_ITEM_CODCOMPONENTE, itemComponente.getCodComponente())
	    								.addValue(PARAM_ITEM_CODIFICACION, itemComponente.getCodificacion())
	    								.addValue(PARAM_ITEM_CODITEMUNION, itemComponente.getItem()==null?null:itemComponente.getItem().getCodItem())
	    								.addValue(PARAM_ITEM_UNIONITEM, itemComponente.getUnionItem());
	    
	    // Establecer parametros y ejecutar SP
	    Map<String,Object> data = llamarSP.execute(parametros);
	    
	    // Obteniendo el total de filas afectadas al ejecutar SP
	    int totalRegistrosAfectado = (Integer) data.get(TOTAL_FILAS_AFECTADAS);
	        
	    return totalRegistrosAfectado;
	}
	
	@Override
	public Item consultarItemInventario(Item item){
		logger.info("consultarItemInventario");
		
		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_CONSULTAR_ITEM_INVENTARIO).
								  returningResultSet(LISTADO, new RowMapper<Item>(){
									@Override
									public Item mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
								        final Item item = new Item();
								        item.setCodItem(rs.getInt(CODITEM));
								        
								        Producto producto = new Producto();
								        producto.setCodigo(rs.getInt(CODPRODUCTO));
								        producto.setCodProductoProveedor(rs.getString(CODPRODUCTOPROVEEDOR));
								        producto.setDescripcion(rs.getString(PRODUCTO_DESCRIPCION));
								        producto.setPrecioVentaMinimo(rs.getDouble(PRODUCTO_PRECIOVENTAMINIMO));
								        producto.setPrecioVentaMaximo(rs.getDouble(PRODUCTO_PRECIOVENTAMAXIMO));
								        producto.setAlto(rs.getDouble(PRODUCTO_ALTO));
								        producto.setAncho(rs.getDouble(PRODUCTO_ANCHO));
								        producto.setLargo(rs.getDouble(PRODUCTO_LARGO));
								        item.setProducto(producto);
								        
								        item.setCodificacion(rs.getString(CODIFICACION));
								        
								        Proveedor proveedor = new Proveedor();
								        proveedor.setCodProveedor(rs.getInt(CODPROVEEDOR));
								        item.setProveedor(proveedor);
								        
								        item.setOrigen(rs.getString(ORIGEN));
								        item.setPropiedades(rs.getString(PROPIEDADES));
								        item.setIncidencias(rs.getString(INCIDENCIAS));
								        item.setPrecioCompra(rs.getDouble(PRECIOCOMPRA));
								        
								        Moneda moneda = new Moneda();
								        moneda.setCodigo(rs.getInt(CODMONEDA));
								        item.setMoneda(moneda);
								        
								        LineaOrdenCompra lineaOrdenCompra = new LineaOrdenCompra(); 
								        lineaOrdenCompra.setCodOC(rs.getInt(CODOC));
								        lineaOrdenCompra.setNumeroLinea(rs.getInt(NROLINEA));
								        item.setLineaOrdenCompra(lineaOrdenCompra);
								        
								        Tienda tienda = new Tienda();
								        tienda.setCodigo(rs.getInt(CODTIENDA));
								        item.setTienda(tienda);
								        
								        item.setEstado(rs.getString(ESTADO));
								        item.setFechaRegistro(rs.getDate(FECHAREGISTRO).toString());
								        return item;
								    }
								  }
								);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	                               .addValue(PARAM_ITEM_CODITEM, item.getCodItem());

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);

        // Obteniendo lista generada de ejecutar SP
		@SuppressWarnings("unchecked")
		List<Item> listaItem = (List<Item>)data.get(LISTADO);
        
		// Declarando objeto item Obtenido
		Item itemObtenido = null;
		
		if (listaItem != null && listaItem.size()>0){
			// Obteniendo el primer elemento de la lista de item
			itemObtenido = listaItem.get(0);	
		}
        
        if (logger.isDebugEnabled() && listaItem != null)
        {
            logger.debug("size=" + listaItem.size());
        }
        
		return itemObtenido;
	}
	
	@Override
	public ListaItemComponente listarItemComponente(Item item) {
		logger.info("listarItemComponente");

		// Instanciando variable para llamado de SP
	    SimpleJdbcCall llamarSP = new SimpleJdbcCall(jdbcTemplate).withProcedureName(SP_LISTAR_ITEM_COMPONENTE).
	    						  returningResultSet(LISTADO, new RowMapper<ItemComponente>(){
									@Override
									public ItemComponente mapRow(final ResultSet rs, final int numRow) throws SQLException
								    {
								        final ItemComponente itemComponente = new ItemComponente();
								        itemComponente.setCodItem(rs.getInt(COMPONENTE_CODITEM));
								        itemComponente.setCodComponente(rs.getInt(COMPONENTE_CODCOMPONENTE));
								        itemComponente.setCodificacion(rs.getString(COMPONENTE_CODIFICACION));

								        Item itemUnion = new Item();
										itemUnion.setCodItem(rs.getInt(COMPONENTE_CODITEMUNION));
										itemComponente.setItem(itemUnion);

								        itemComponente.setUnionItem(rs.getString(COMPONENTE_UNIONITEM));
								        
								        return itemComponente;
								    }
	    						  }
								);

	    // Estableciendo parametros de entrada al SP
	    SqlParameterSource parametros = new MapSqlParameterSource()
	    								.addValue(PARAM_CODITEM, item.getCodItem()); 

	    // Establecer parametros y ejecutar SP
        Map<String,Object> data = llamarSP.execute(parametros);

        // Obteniendo lista generada de ejecutar SP
		@SuppressWarnings("unchecked")
		List<ItemComponente> listaItemComponente = (List<ItemComponente>)data.get(LISTADO);
        
		// Instanciando objeto ListaItem
		ListaItemComponente listaItemComponenteResultado = new ListaItemComponente();
        // Estableciendo resultado al objeto listaItemComponenteResultado
		
		listaItemComponenteResultado.setLista(listaItemComponente);
        
        if (logger.isDebugEnabled() && listaItemComponenteResultado != null)
        {
            logger.debug("size=" + listaItemComponenteResultado.size());
        }
        return listaItemComponenteResultado;
	}
}
